package com.zoo.boot.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.zoo.boot.bean.JwtUser;
import com.zoo.boot.model.LMenu;
import com.zoo.boot.model.LRole;
import com.zoo.boot.model.LUser;
import com.zoo.boot.service.MenuService;
import com.zoo.boot.service.RedisService;
import com.zoo.boot.service.RoleService;
import com.zoo.boot.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 登录授权与认证实现 Service
 *
 * @Author: WangB
 * @Date: 2021/6/25
 */
@Service
public class UserDetailsServiceImpl implements UserDetailsService {

    @Autowired
    private UserService userService;

    @Autowired
    private RoleService roleService;

    @Autowired
    private MenuService menuService;

    @Autowired
    private RedisService redisService;


    /**
     * 表单数据 提交给 security  ===>　　将username和password 封装成 Token。
     * 然后调用你的 UserDetailsServiceImpl 的 loadUserByUsername(String  username) 获取一些可以判断认证和授权的数据依据。
     * <p>
     * Security 接收的数据依据以 UserDetails 类型返回。
     * <p>
     * <p>
     * exp：取出 JwtUser 的密码 和 token 对象中的密码比对 ，如果 成功 ，将整个 JwtUser对象保存在内存中。
     *
     * @param username
     * @return
     * @throws UsernameNotFoundException
     */
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {






        LUser lUser = userService.loginByUsername(username);

        if (ObjectUtil.isEmpty(lUser)) {
            throw new BadCredentialsException("用户名不正确或者不存在");
        }


        //获取角色信息
        LRole lRole = roleService.getRoleByUserId(lUser.getUserId());

        if (ObjectUtil.isEmpty(lRole)) {
            throw new BadCredentialsException("该用户还没有绑定角色信息");
        }

        List<LMenu> list = (List<LMenu>) redisService.get("repast:menu:" + lUser.getUserId());

        List<LMenu> menuByRoleId = null;

        if (ObjectUtil.isEmpty(list)) {
            //获取菜单信息
            menuByRoleId = menuService.getMenuByRoleId(lRole.getRoleId());

            redisService.set("repast:menu:" + lUser.getUserId(), menuByRoleId);

        } else {
            menuByRoleId = list;
        }

        //获取权限信息
        List<String> collect = menuByRoleId.stream().map(LMenu::getPermission).collect(Collectors.toList());

        List<GrantedAuthority> authorities = new ArrayList<>();

        collect.stream().forEach(grant -> {
            if (ObjectUtil.isNotEmpty(grant)) {
                authorities.add(new SimpleGrantedAuthority(grant));
            }
        });

        JwtUser jwtUser = new JwtUser(lUser, lRole, menuByRoleId, authorities);
        return jwtUser;
    }
}
